package pl.com.sthaether.mc.engine;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import javafx.scene.shape.Circle;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.text.Text;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import org.geotools.data.FileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.opengis.feature.simple.SimpleFeature;
import pl.com.sthaether.mc.engine.data.MCMapDataObject;
import pl.com.sthaether.mc.exception.MCExceptionHandler;

import java.io.IOException;

public class MCMapFactory {


    private MCMapFactory() {
    }

    public static MCMap createEmptyMap() {
        MCMap map = new MCMap();

        return map;
    }

    public static MCMap createMapFromSHPFile(FileDataStore store) {
        MCMap map = new MCMap();
        int id = 0;
        SimpleFeatureCollection c = null;
        try {
            c = store.getFeatureSource().getFeatures();
        } catch (IOException e) {
            MCExceptionHandler.handleException(e);
        }
        //TODO make choice of key property name
        SimpleFeatureIterator featuresIterator = c.features();
        Coordinate[] coordinates = new Coordinate[0];
        Geometry polygon;
        while (featuresIterator.hasNext()) {
            SimpleFeature o = featuresIterator.next();
//            System.out.println(o.getAttributes());//TODO attributes list
            String name = (String) o.getAttribute("name");
            if (name == null) {
                name = (String) o.getAttribute("VARNAME_1");
            }
            Object geometry = o.getDefaultGeometry();
            if (geometry instanceof MultiPolygon) {
                while (map.getData().containsObject(String.valueOf(id))) {
                    id++;
                }
                MCMapDataObject obj = new MCMapDataObject((name != null ? name : String.valueOf(id++)), (MultiPolygon) geometry);

                for (int geometryI = 0; geometryI < obj.getShape().getNumGeometries(); geometryI++) {
                    polygon = obj.getShape().getGeometryN(geometryI);

                    coordinates = polygon.getCoordinates();
                    Path path = new Path();
                    path.setStrokeWidth(0.02);
                    path.getElements().add(new MoveTo(coordinates[0].x, coordinates[0].y));
                    for (int i = 1; i < coordinates.length; i++) {
                        path.getElements().add(new LineTo(coordinates[i].x, coordinates[i].y));
                    }
                    path.getElements().add(new LineTo(coordinates[0].x, coordinates[0].y));
                    obj.addPath(path);

                }
                map.getData().addMapObject(obj);
            } else if (geometry instanceof Point) {
                System.out.println("unsupported part of file - Point types");
                Circle circle = new Circle();
                circle.setStrokeWidth(0.02);
                circle.setCenterX(((Point) geometry).getX());
                circle.setCenterY(((Point) geometry).getY());
                circle.setRadius(0.2);
                Text text = new Text((name != null ? name : String.valueOf(id++)));
                text.getTransforms().add(new Translate(((Point) geometry).getX(), ((Point) geometry).getY() + 1.5));
                text.getTransforms().add(new Scale(0.1, -0.1));
                text.getTransforms().add(new Translate(-text.getBoundsInLocal().getWidth() / 2., text.getBoundsInLocal().getHeight() / 2.));
                map.getGroup().getChildren().add(circle);
                map.getGroup().getChildren().add(text);

            }
        }

        map.getGroup().scaleXProperty().set(5);
        map.getGroup().scaleYProperty().set(-5);


        map.getData().updateInfoGroup(map.getGroup().getBoundsInLocal().getMaxX(), map.getGroup().getBoundsInLocal().getMaxY(),map.getGroup().getBoundsInLocal().getMinX());
        return map;
    }


}
